昨天我們了解了字串及與它相關的一些功能,這些功能被稱為函式 Function,也是我們今天要討論的主題。
函式的概念是用來執行某種作業的程式碼區塊。我們可以把它想像為程式碼版的變數,只是它的內容物不再是某種資料的值,而是代表一項功能的程式碼,而且我們沒辦法在程式運行時隨意改變它的內容。透過使用函式,我們便可以把一些經常使用的功能或部分的程式碼封裝起來並在需要時呼叫該函式,這樣便讓我們不需要重複編寫一些常用的功能。
舉例來說,假設現在我們需要計算兩個班級的平均分,在使用函式的狀況下,我們便可以不用把計算平均分的部分重複編寫兩次:[Python]
def average(scores):
# 計算平均分的部分
total = 0
for score in scores:
total += score
return total/len(scores) # 回傳結果
classA = [80, 90, 50, 75, 65]
classB = [70, 40, 60, 80, 95]
print("A 班的平均分 = " + str(average(classA))) # 使用陣列 classA 來呼叫函式 average 來獲取平均分並轉換為 string 後將其顯示出來
print("B 班的平均分 = " + str(average(classB))) # 使用陣列 classB 來呼叫函式 average 來獲取平均分並轉換為 string 後將其顯示出來
跟變數相似,當我們想要使用函式前,我們必須要先把它準備好。不過,這次我們不再是再程式中宜告它,而是要定義它,也就是完整的把整個功能都編寫好。
一般定義函式時會可能需要包含以下的要素:
1. 宣告定義函式的關鍵詞組
我們必須告訴程式哪部分的程式碼是屬於函式,因此我們需要以固定的格式來編寫,而函式的格式則視程式語言而定,如 Python 是 def [函式名稱]([函式參數])
、而 C# 則是 public/protected/private [static] [函式回傳資料型態] [函式名稱]([函式參數])
。
2. 函式名稱
如同變數一樣,為了能讓我們分辨不同的函式,我們需要為它們命名。
3. 函式回傳資料型態
大多數的程式語言在定義函式時都需要宣告它的回傳資料型態來告訴程式這個函式完結時會回傳什麼資料,如果函式不會回傳任何資料的話,通常可以使用 void 關鍵字來代替。
4. 函式参數
有時候我們所呼叫的函式會需要我們在呼叫時提供一些資料來讓它在執行時使用,這些執行時需要提供的資料被稱為參數 (Parameter),跟函式回傳資料型態一樣,都需要在定義函式時宣告它來讓程式在呼叫該函式時知道要接收什麼資料並將其輸入到函式中。
5. 區塊的開始與結束
我們需要指定函式的開始與結束位置來告訴程式哪部分的程式碼是屬於函式的,而開始與結束位置之間的區域則被稱為區塊 (Block)。指定區塊的方式視程式語言而定,不過大多數的程式都是使用大括號 {}
來表示區塊的開始與結束。
6. return 陳述式
在[DAY 12] 改變程式流程的跳躍陳述式中便曾提到:
return 陳述式的目的不是中斷正在執行的陳述式而是中斷正在執行的函式 (Functions)。
return 陳述式在函式中有兩個主要的功能:
(1) 中斷正在執行的函式
(2) 回傳指定的資料
因此,我們通常會在需要回傳資料或在函式的中間中斷執行時會使用 return 陳述式。需要注意的是,假如我們宣告的函式回傳資料型態不是 void 時便必須使用 return 陳述式結束函式來確定有資料被回傳。
接下來就讓我們來看一下在 C# 如何定義函式吧:
[函式回傳資料型態]
| [函式名稱]
| | [函式参數]
V V V
public static int someFunction(int n) { [函式區塊開始]
int sum = 0;
// 一些程式碼
return sum; [return 陳述式]
} [函式區塊結束]
不知道大家有沒有感覺這格式很眼熟?沒錯,它跟我們平常使用 C# 時的主要區塊的格式完全一樣! 這是因為我們在編寫的主要區塊部分實際上也是使用一個函式來把程式碼封裝起來,這個函式一般會被稱為主函式 (Main Function)。只是這個主函式並不是由我們來呼叫,而是使用在程式執行時由電腦自動呼叫。不過,有些程式語言,如 Python,為了讓程式可以變得更簡潔,便捨棄了主函式的設計,改為直接讀取所有的程式碼。
C# 的主要區塊[主函式]:
[函式回傳資料型態]
| [函式名稱]
| | [函式参數]
V V V
public static void Main(string[] args)
{ [函式區塊開始]
// 一般編寫程式的部分
} [函式區塊結束]
由於主要區塊部分也是一個函式,因此當我們想要定義新的函式時,需要在主函式外的區域進行。以下是完整的使用函式的例子:[C#]
using System;
public class FunctionExample
{
// 我們自訂的函式 getSum
public static int getSum(int n) {
int sum = 0; // 宣告變數 sum 並指定值為 0
for (int i = 1; i <= n; i++) { // for 迴圈
sum += i; // 把變數 i 的值加到變數 sum 並儲存起來
}
return sum; // 回傳變數 sum 的值
}
// 主函式
public static void Main(string[] args)
{
Console.WriteLine (getSum(10)); // 呼叫函式 getSum 並指定參數 n 的值為 10,在獲取回傳的資料後把它顯示出來
}
}
為什麼我們需要特別的把部分的程式碼從主函式中分離出來編寫成函式呢?以下是使用函式的優點:
1. 可重複使用:
如前文所述,透過使用函式,我們便不用把經常被使用的程式碼或功能重複編寫很多遍。
2. 讓主函式保持簡潔、易讀
把部分的程式碼或功能做成函式後,主函式的內容便會變得較簡潔,這樣在日後我們需要重新理解這個程式或與他人一起合作時要理解程式的邏輯時會變得輕鬆許多。
3. 較容易修改功能
由於功能的部分被獨立出來,因此我們可以更容易集中關注該功能並進行修改。這在修正程式錯誤時有非常大的幫助,因為我們能大幅縮減了錯誤出現的範圍。另一方面,修改函式時亦較不容易影響到程式的其他部分,避免出現大量錯誤的連鎖的情況。